package com.hippo4j.executor;

import com.hippo4j.plugin.ShutdownAwarePlugin;
import com.hippo4j.plugin.manager.ThreadPoolPluginManager;

import java.util.List;
import java.util.concurrent.*;

public class ExtensibleThreadPoolExecutor extends ThreadPoolExecutor {

    private final String threadPoolId;

    private ThreadPoolPluginManager pluginManager;


    private RejectedAwareHandlerWrapper rejectedAwareHandlerWrapper;


    public String getThreadPoolId() {
        return threadPoolId;
    }

    @Override
    protected void beforeExecute(Thread t, Runnable r) {
        pluginManager.getExecuteAwarePluginList().forEach(plugin -> plugin.beforeExecute(t, r));
    }

    @Override
    protected void afterExecute(Runnable r, Throwable t) {
        pluginManager.getExecuteAwarePluginList().forEach(plugin -> plugin.afterExecute(r, t));

    }

    @Override
    public void execute(Runnable command) {

        super.execute(command);

    }


    @Override
    public void shutdown() {
        List<ShutdownAwarePlugin> shutdownAwarePluginList = (List<ShutdownAwarePlugin>) pluginManager.getShutdownAwarePluginList();
        shutdownAwarePluginList.forEach(plugin -> plugin.beforeShutdown(this));
        super.shutdown();
        shutdownAwarePluginList.forEach(plugin -> plugin.afterShutdown(this));
    }

    public ExtensibleThreadPoolExecutor(String threadPoolId, int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler, ThreadPoolPluginManager pluginManager) {
        super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, threadFactory, handler);

        this.threadPoolId = threadPoolId;
        this.pluginManager = pluginManager;

        //又包装了一层
        this.rejectedAwareHandlerWrapper = new RejectedAwareHandlerWrapper(this.pluginManager, handler);
        super.setRejectedExecutionHandler(rejectedAwareHandlerWrapper);
    }


    public ThreadPoolPluginManager getPluginManager() {
        return pluginManager;
    }

    private static class RejectedAwareHandlerWrapper implements RejectedExecutionHandler {

        private final ThreadPoolPluginManager pluginManager;

        private RejectedExecutionHandler handler;

        public RejectedAwareHandlerWrapper(ThreadPoolPluginManager pluginManager, RejectedExecutionHandler handler) {
            this.pluginManager = pluginManager;
            this.handler = handler;
        }

        @Override
        public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
            this.pluginManager.getRejectAwarePluginList().forEach(plugin -> plugin.beforeReject(r, executor));

            this.handler.rejectedExecution(r, executor);
        }
    }
}



